package com.kly.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kly.constants.UserConstant;
import com.kly.domain.dto.space.SpaceAnalysisRequest;
import com.kly.domain.dto.space.SpaceRankAnalyzeRequest;
import com.kly.domain.dto.space.SpaceUserAnalysisRequest;
import com.kly.domain.entity.Picture;
import com.kly.domain.entity.Space;
import com.kly.domain.entity.User;
import com.kly.domain.enums.UserRoleEnum;
import com.kly.domain.vo.space.*;
import com.kly.exception.BusinessException;
import com.kly.exception.ErrorCode;
import com.kly.exception.ThrowUtils;
import com.kly.mapper.SpaceMapper;
import com.kly.service.PictureService;
import com.kly.service.SpaceAnalysisService;
import com.kly.service.SpaceService;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【space(空间)】的数据库操作Service实现
 * @createDate 2025-03-11 12:40:49
 */
@Service
@RequiredArgsConstructor
public class SpaceAnalysisServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceAnalysisService {

    private final PictureService pictureService;

    private final SpaceService spaceService;


    @Override
    public void checkSpaceAnalysisAuth(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        //     校验参数
        ThrowUtils.throwIf(spaceAnalysisRequest == null, ErrorCode.PARAMS_ERROR, "spaceAnalysisRequest不能为空");
        //     管理员可以查询全部和公开分析
        if (spaceAnalysisRequest.isQueryPublic() || spaceAnalysisRequest.isQueryAll()) {
            ThrowUtils.throwIf(!UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()), ErrorCode.NO_AUTH_ERROR);
        }
        //      个人只能查询自己空间分析
        Long spaceId = spaceAnalysisRequest.getSpaceId();
        Space space = this.getById(spaceId);
        if (spaceId != null) {
            ThrowUtils.throwIf(!space.getUserId().equals(loginUser.getId()) && !UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()), ErrorCode.NO_AUTH_ERROR, "没有权限");
        }
    }

    @Override
    public void checkSpaceAuth(Space space, User loginUser) {
        ThrowUtils.throwIf(!space.getUserId().equals(loginUser.getId()) || !UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()), ErrorCode.NO_AUTH_ERROR, "没有权限");
    }

    @Override
    public void fillQueryWrapper(SpaceAnalysisRequest spaceAnalysisRequest, QueryWrapper<Picture> queryWrapper) {
        //     校验参数
        ThrowUtils.throwIf(spaceAnalysisRequest == null, ErrorCode.PARAMS_ERROR, "spaceAnalysisRequest不能为空");
        Long spaceId = spaceAnalysisRequest.getSpaceId();
        boolean queryPublic = spaceAnalysisRequest.isQueryPublic();
        boolean queryAll = spaceAnalysisRequest.isQueryAll();
        // 查询全部
        if (queryAll) {
            return;
        }

        //     查询公开
        if (queryPublic) {
            queryWrapper.isNull("space_id");
            return;
        }
        //     查询特定
        if (spaceId != null) {
            queryWrapper.eq("space_id", spaceId);
            return;
        }

        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询参数");
    }

    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        QueryWrapper<Picture> queryWrapper = getPictureQueryWrapperAndCheckAuth(spaceAnalysisRequest, loginUser);
        // 4. 返回结果
        Long spaceId = spaceAnalysisRequest.getSpaceId();
        boolean queryPublic = spaceAnalysisRequest.isQueryPublic();
        boolean queryAll = spaceAnalysisRequest.isQueryAll();
        SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
        // 4.1 如果是公有或全部条件
        if (queryAll || queryPublic) {
            //     查询picSize
            queryWrapper.select("pic_size");
            List<Object> objectList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            //     length
            long size = objectList.size();
            //     size
            long sum = objectList.stream().filter(Objects::nonNull).mapToLong(o -> Long.parseLong(o.toString())).sum();
            spaceUsageAnalyzeResponse.setUsedCount(size);
            spaceUsageAnalyzeResponse.setUsedSize(sum);
            return spaceUsageAnalyzeResponse;
        }
        // 4.2 如果是特定条件
        if (spaceId != null) {
            //     查询空间
            Space spaceDb = this.getById(spaceId);
            ThrowUtils.throwIf(spaceDb == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            //     设置值
            spaceUsageAnalyzeResponse.setUsedCount(spaceDb.getTotalCount());
            spaceUsageAnalyzeResponse.setUsedSize(spaceDb.getTotalSize());
            spaceUsageAnalyzeResponse.setMaxCount(spaceDb.getMaxCount());
            spaceUsageAnalyzeResponse.setMaxSize(spaceDb.getMaxSize());
            double countUsageRatio = NumberUtil.round(spaceDb.getTotalCount() * 100.0 / spaceDb.getMaxCount(), 2).doubleValue();
            spaceUsageAnalyzeResponse.setCountUsageRatio(countUsageRatio);
            double sizeUsageRatio = NumberUtil.round(spaceDb.getTotalSize() * 100.0 / spaceDb.getMaxSize(), 2).doubleValue();
            spaceUsageAnalyzeResponse.setSizeUsageRatio(sizeUsageRatio);
            return spaceUsageAnalyzeResponse;
        }
        return spaceUsageAnalyzeResponse;
    }

    private @NotNull QueryWrapper<Picture> getPictureQueryWrapperAndCheckAuth(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        // 1. 检验参数
        ThrowUtils.throwIf(spaceAnalysisRequest == null, ErrorCode.PARAMS_ERROR, "spaceAnalysisRequest不能为空");
        // 2. 填充查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillQueryWrapper(spaceAnalysisRequest, queryWrapper);
        // 3. 校验权限
        checkSpaceAnalysisAuth(spaceAnalysisRequest, loginUser);
        return queryWrapper;
    }

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        // 1. 检验参数
        QueryWrapper<Picture> queryWrapper = getPictureQueryWrapperAndCheckAuth(spaceAnalysisRequest, loginUser);
        // 4. 查询 mybatis 聚合函数
        queryWrapper.select("category", "count(*) as count", "sum(pic_size) as size");
        // 分组和排序
        queryWrapper.groupBy("category").orderByDesc("size");
        return pictureService.getBaseMapper().selectMaps(queryWrapper).stream()
                .map(item -> {
                    String category = (String) item.get("category");
                    Long totalCount = Long.valueOf(item.get("count").toString());
                    Long totalSize = Long.valueOf(item.get("size").toString());
                    return new SpaceCategoryAnalyzeResponse(category, totalCount, totalSize);
                }).collect(Collectors.toList());
    }

    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        QueryWrapper<Picture> queryWrapper = getPictureQueryWrapperAndCheckAuth(spaceAnalysisRequest, loginUser);
        // 4. 查询标签列
        queryWrapper.select("tags");
        List<Object> tagsJsonList = pictureService.getBaseMapper().selectObjs(queryWrapper);
        ThrowUtils.throwIf(CollUtil.isEmpty(tagsJsonList), ErrorCode.NOT_FOUND_ERROR, "未找到标签");

        // 转换
        Map<String, Long> tagCountMap = tagsJsonList.stream()
                .filter(Objects::nonNull)
                .map(Object::toString)
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        return tagCountMap.entrySet().stream()
                .sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceAnalysisRequest spaceAnalysisRequest, User loginUser) {
        QueryWrapper<Picture> queryWrapper = getPictureQueryWrapperAndCheckAuth(spaceAnalysisRequest, loginUser);

        // 查询列
        queryWrapper.select("pic_size");
        List<Object> picSizeList = pictureService.getBaseMapper().selectObjs(queryWrapper);


        Map<String, Long> sizeRangeMap = new LinkedHashMap<>();
        picSizeList.stream().filter(Objects::nonNull)
                .map(Object::toString)
                .map(Long::parseLong)
                .forEach(picSize -> {
                    if (picSize < 1024 * 100) {
                        sizeRangeMap.put("<100KB", sizeRangeMap.getOrDefault("<100KB", 0L) + 1);
                    } else if (picSize < 1024 * 1024 * 10) {
                        sizeRangeMap.put("100KB-10MB", sizeRangeMap.getOrDefault("100KB-10MB", 0L) + 1);
                    } else if (picSize < 1024 * 1024 * 100) {
                        sizeRangeMap.put("10MB-100MB", sizeRangeMap.getOrDefault("10MB-100MB", 0L) + 1);
                    } else if (picSize < 1024 * 1024 * 1024) {
                        sizeRangeMap.put("100MB-1GB", sizeRangeMap.getOrDefault("100MB-1GB", 0L) + 1);
                    }
                });
        // 选择size
        return sizeRangeMap.entrySet()
                .stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalysisRequest spaceUserAnalysisRequest, User loginUser) {
        //     校验
        QueryWrapper<Picture> queryWrapper = getPictureQueryWrapperAndCheckAuth(spaceUserAnalysisRequest, loginUser);
        // 校验权限 判断是不是管理员
        if (!UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
        }
        // 查询时间段
        Long userId = spaceUserAnalysisRequest.getUserId();
        String timeDimension = spaceUserAnalysisRequest.getTimeDimension();
        // 查询指定id
        queryWrapper.eq(userId != null, "user_id", userId);
        // 查询时间维度
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(create_time, '%y-%m-%d') as period", "count(*) as count");
                break;
            case "week":
                queryWrapper.select("DATE_FORMAT(create_time, '%y-%u') as period", "count(*) as count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(create_time, '%y-%m') as period", "count(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "时间维度错误");
        }
        // 分组和排序
        queryWrapper.groupBy("period").orderByDesc("period");
        // 查询结果
        return pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(item -> {
                    String period = (String) item.get("period");
                    Long count = (Long) item.get("count");
                    return new SpaceUserAnalyzeResponse(period, count);
                }).collect(Collectors.toList());
    }

    @Override
    public List<Space> getSpaceTop5Analyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        // 校验
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 查询条件
        if (!UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
        }
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id, space_name, user_id, total_size")
                .last("ORDER BY total_size DESC LIMIT " + spaceRankAnalyzeRequest.getTopN());
        return spaceService.list(queryWrapper);
    }


}




